# Start the imports

import os
import wx

import extern.ultimatelistctrl as ULC
import extern.listctrl as listmix

from utilities import shortNow
from constants import _iconMapper, _messageImageList, _messageColumnNames


class MessageWindow(ULC.UltimateListCtrl, listmix.ListCtrlAutoWidthMixin):

    def __init__(self, parent, columnNames=_messageColumnNames, images=_messageImageList):
        """
        Default class constructor.

        :param `parent`: the parent widget
        :param `columnNames`: the list control column names
        """

        ULC.UltimateListCtrl.__init__(self, parent, -1, style=wx.SUNKEN_BORDER, agwStyle=wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES|wx.LC_VIRTUAL)

        # Initialize the auto width mixin. We always need it        
        listmix.ListCtrlAutoWidthMixin.__init__(self)
        self.MainFrame = wx.GetTopLevelParent(self)

        self.popupId1, self.popupId2 = wx.NewId(), wx.NewId()
        self.messages = []
        self.textColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOXTEXT)

        self.EnableSelectionVista()
        
        # Do the hard work
        self.BuildImageList(images)
        self.InsertColumns(columnNames)
        self.BindEvents()

        self.SetItemCount(200)


    # ========================== #
    # Methods called in __init__ #
    # ========================== #
    
    def InsertColumns(self, columnNames):
        """ Inserts the columns in the list control. """

        # The first column is always empty text, as I use it to display
        # an informative/fancy icon
        self.InsertColumn(0, "")

        # Loop over all the column names        
        for indx, column in enumerate(columnNames):
            self.InsertColumn(indx+1, column)
            self.SetColumnWidth(indx+1, wx.LIST_AUTOSIZE_USEHEADER)

        # The first column only displays an icon, 24 is perfect on Windows
        self.SetColumnWidth(0, 24)


    def BuildImageList(self, images):
        """ Build the image list for the list control. """
        
        # Ok, here it gets tricky as I am trying to re-use the same base class
        # for 6 or more different list control
        imgList = wx.ImageList(16, 16)

        # Loop over all the images in the list
        for png in images:
            imgList.Add(self.MainFrame.CreateBitmap(png))

        # Assign the image list, I don't want to store it            
        self.AssignImageList(imgList, wx.IMAGE_LIST_SMALL)            
        
        
    def BindEvents(self):
        """ Bind the events for the list control. """

        self.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnRightClick)
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick)
        self.Bind(wx.EVT_LIST_COL_BEGIN_DRAG, self.OnColumnDrag)

        self.Bind(wx.EVT_MENU, self.OnExportMessages, id=self.popupId1)
        self.Bind(wx.EVT_MENU, self.OnHistoryClear, id=self.popupId2)


    def OnColumnDrag(self, event):
        """ Handles the wx.EVT_LIST_COL_BEGIN_DRAG event for the list control. """

        if event.GetColumn() == 0:
            # Veto the event for the first column, it holds the icon
            event.Veto()
            return

        event.Skip()


    def OnRightClick(self, event):
        """
        Handles the wx.EVT_LIST_COL_RIGHT_CLICK/wx.EVT_LIST_ITEM_RIGHT_CLICK
        event for the list control.
        """

        menu = wx.Menu()

        item = wx.MenuItem(menu, self.popupId1, "Export messages")
        bmp = self.MainFrame.CreateBitmap("export")
        item.SetBitmap(bmp)
        menu.AppendItem(item)        

        item = wx.MenuItem(menu, self.popupId2, "Clear history")
        bmp = self.MainFrame.CreateBitmap("history_clear")
        item.SetBitmap(bmp)
        menu.AppendItem(item)        

        # Popup the menu.  If an item is selected then its handler
        # will be called before PopupMenu returns.
        self.PopupMenu(menu)


    def OnHistoryClear(self, event):
        """ Handles the wx.EVT_MENU event for the list control. """

        # Freeze everything... It helps with flicker
        self.Freeze()
        # Delete all the items, the user cleared all
        self.DeleteAllItems()

        self.messages = []
        self.SetItemCount(200)
        
        # Time to warm up
        self.Thaw()
                

    def OnExportMessages(self, event):

        pass
    

    # ================= #
    # Auxiliary methods #
    # ================= #

    
    def SendMessage(self, kind, message):
        """ Prints an user-friendly message on the list control. """

        messages = [msg[2] for msg in self.messages]
                
        lenMess = len(self.messages)
        itemCount = self.GetItemCount()
        
        if lenMess == itemCount-1:
            self.SetItemCount(itemCount+200)

        # Get the current time slightly dirrently formatted
        currentTime = shortNow()

        self.messages.append((kind, currentTime, message))        
            
        # Ensure the last item is visible
        if lenMess > 3:
            self.EnsureVisible(lenMess)
            
        self.Refresh()
        self.Update()


    def OnGetItemText(self, item, col):

        lenMess = len(self.messages)

        if lenMess == 0 or col == 0 or item >= lenMess:
            return ""

        return self.messages[item][col]
        

    def OnGetItemImage(self, item):

        lenMess = len(self.messages)

        if lenMess == 0 or item >= lenMess:
            return []

        kind = self.messages[item][0]
        return _iconMapper[kind]


    def OnGetItemTextColour(self, item, col):

        return self.textColour
    

    def OnGetItemToolTip(self, item, col):

        return ""

